package com.wjf.userservice.service.impl;

import com.wjf.userservice.entity.User;
import com.wjf.userservice.entity.Permission;
import com.wjf.userservice.mapper.UserMapper;
import com.wjf.userservice.mapper.RoleMapper;
import com.wjf.userservice.service.UserService;
import com.wjf.common.utils.JwtUtils;
import com.wjf.common.utils.ThreadLocalUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestHeader;
import redis.clients.jedis.Jedis;

import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.io.ObjectOutputStream;

@Service
public class UserServiceImpl implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    private static final Long DEFAULT_ROLE_ID = 4L; // 普通用户角色ID

    @Override
    @Transactional
    public String login(String username, String password) {
        try {
            log.info("开始登录 - 用户名: {}", username);

            // 先根据用户名查询用户
            User user = userMapper.findByUsername(username);
            log.info("查询到的用户信息: {}", user);

            if (user == null) {
                log.info("用户名不存在: {}", username);
                return null;
            }

            // 验证密码
            boolean matches = passwordEncoder.matches(password, user.getPassword());
            log.info("密码匹配结果: {}", matches);

            if (!matches) {
                log.info("密码错误 - 用户名: {}", username);
                return null;
            }

            // 生成JWT令牌
            Map<String, Object> claims = new HashMap<>();

            
            claims.put("userId", user.getId());
            claims.put("username", user.getUsername());
  
            String token = JwtUtils.generateToken(claims);
            log.info("生成的token: {}", token);


            try {
                // 将token存入Redis
                log.info("存入Redis的token key: {}", token);
                redisTemplate.opsForValue().set(token, token, 24, TimeUnit.HOURS);
                log.info("token已存入Redis");

            } catch (Exception e) {
                log.error("Redis操作失败", e);
                throw new RuntimeException("登录失败：Redis操作异常");
            }
            log.info("开始存入用户信息：{}",user);
            Jedis jedis = new Jedis("localhost",6379);
            log.info("jedis连接：{}",jedis.ping());
            try {
                // 将用户信息存入redis
                // 将用户对象序列化为字节数组
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(user);
                byte[] userBytes = bos.toByteArray();

                // 将字节数组存入Redis
                jedis.set(user.getUsername().toString().getBytes(), userBytes);

                log.info("用户对象已成功存入Redis");
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                jedis.close();
            }

            return token;
        } catch (Exception e) {
            log.error("登录过程发生异常", e);
            throw new RuntimeException("登录失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public boolean register(User user) {
        // 检查用户名是否已存在
        if (userMapper.checkUsername(user.getUsername()) > 0) {
            return false;
        }

        // 设置默认值
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        user.setStatus(1);
        user.setVipLevel(0);
        user.setCreateTime(new Date());

        // 注册用户
        if (userMapper.register(user) <= 0) {
            return false;
        }

        // 分配默认角色
        try {
            userMapper.assignUserRole(user.getId(), DEFAULT_ROLE_ID, new Date());
            return true;
        } catch (Exception e) {
            log.error("分配用户角色失败", e);
            throw new RuntimeException("注册失败：分配角色异常");
        }
    }

    @Override
    public User getCurrentUser() {
        // 从ThreadLocal中获取当前用户信息
        Map<String, Object> claims = ThreadLocalUtils.get("claims");
        if (claims == null) {
            return null;
        }
        Jedis jedis = new Jedis("localhost",6379);
        byte[] usernames = jedis.get(claims.get("username").toString().getBytes());

        User user = null;
        try {
            ByteArrayInputStream bis = new ByteArrayInputStream(usernames);
            ObjectInputStream ois = new ObjectInputStream(bis);
            user = (User) ois.readObject();
            ois.close();
            bis.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }finally {
            jedis.close();
        }

        return user;
    }

    @Override
    public boolean logout(String token) {
        try {
            // 只需要从Redis中删除token
            Boolean deleted = redisTemplate.delete(token);
            return Boolean.TRUE.equals(deleted);
        } catch (Exception e) {
            log.error("注销失败", e);
            return false;
        }
    }

    @Override
    public boolean updateUserInfo(User user) {
        try {
            User currentUser = getCurrentUser();
            if (currentUser == null) {
                return false;
            }

            // 只检查提供的字段
            if (StringUtils.hasText(user.getUsername()) &&
                    !user.getUsername().equals(currentUser.getUsername())) {
                if (userMapper.checkUsernameExist(user.getUsername(), currentUser.getId()) > 0) {
                    throw new RuntimeException("用户名已被使用");
                }
            }

            if (StringUtils.hasText(user.getEmail()) &&
                    !user.getEmail().equals(currentUser.getEmail())) {
                if (userMapper.checkEmailExist(user.getEmail(), currentUser.getId()) > 0) {
                    throw new RuntimeException("邮箱已被使用");
                }
            }

            if (StringUtils.hasText(user.getPhone()) &&
                    !user.getPhone().equals(currentUser.getPhone())) {
                if (userMapper.checkPhoneExist(user.getPhone(), currentUser.getId()) > 0) {
                    throw new RuntimeException("手机号已被使用");
                }
            }

            // 设置不允许修改的字段
            user.setId(currentUser.getId());
            user.setUpdateTime(new Date());

            // 只更新提供的字段
            return userMapper.updateUser(user) > 0;
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            throw new RuntimeException("更新用户信息失败：" + e.getMessage());
        }
    }

    @Override
    @Transactional
    public boolean changePassword(String oldPassword, String newPassword,String token) {
        try {
            log.info("开始修改密码");

            User currentUser = getCurrentUser();
            if (currentUser == null) {
                log.warn("修改密码失败：未获取到当前用户信息");
                return false;
            }
            log.info("当前用户ID: {}, 用户名: {}", currentUser.getId(), currentUser.getUsername());

            // 验证旧密码
            boolean matches = passwordEncoder.matches(oldPassword, currentUser.getPassword());
            log.info("旧密码验证结果: {}", matches);

            if (!matches) {
                log.warn("修改密码失败：旧密码验证失败");
                return false;
            }

            // 加密新密码
            String encodedNewPassword = passwordEncoder.encode(newPassword);
            log.debug("新密码已加密");

            // 更新密码
            boolean updated = userMapper.updatePassword(currentUser.getId(),
                    encodedNewPassword, new Date()) > 0;

            if (updated) {
                log.info("密码修改成功 - 用户ID: {}", currentUser.getId());

                
                if (token != null) {
                    // 删除当前用户的token
                    redisTemplate.delete(token);
                    log.info("已清除用户token: {}", token);
                }

                return true;
            } else {
                log.error("密码修改失败：数据库更新失败");
                return false;
            }
        } catch (Exception e) {
            log.error("修改密码过程发生异常", e);
            return false;
        }
    }

    @Override
    public boolean checkUsernameAvailable(String username) {
        return userMapper.checkUsername(username) == 0;
    }

    @Override
    public boolean checkPermission(String code) {
        // 获取用户信息
        User currentUser = getCurrentUser();
        // 获取用户权限信息
        List<Permission> permissions = currentUser.getPermissions();
        boolean flag = false;
        for (Permission permission : permissions) {
            if(permission.getCode().equals(code)){
                return true;
            }
        }

        return flag;
    }
}
